package de.szut.pongsim.physics;

import java.util.Random;

public class BallFunction {

	public static final int LOWER_LAUNCH_BOUND = -70;
	public static final int UPPER_LAUNCH_BOUND = 70;
	
	private double m;
	private double b;
	
	private BallFunction(double m, double b) {
		this.m = m;
		this.b = b;
	}
	
	public Point next(HorizontalDirection dir, Point current) {
		int nextX = current.getX() + dir.getNextStep();
		int nextY = (int) (m*nextX + b);
		Point next = new Point(nextX, nextY);
		return next;
	}
	
	private static double angleToSlope(double angle) {
		return Math.tan(Math.toRadians(angle));
	}
	
	private static double intersection(Point impact, double m) {
		return impact.getY() - m*impact.getX();
	}
	
	private static double slopeToAngle(double m) {
		return Math.toDegrees(Math.atan(m));
	}
	
	private static double randomAngle(double from, double to) {
		Random ran = new Random();
		return ran.doubles(from, to).findFirst().getAsDouble();
	}
	
	public void rebound(Point impact) {
		m = -m;
		b = intersection(impact, m);
	}
	
	private void randomRebound(Point impact, double from, double to) {
		double randomizedAngle = randomAngle(from, to);
		m = angleToSlope(randomizedAngle);
		b = intersection(impact, m);
	}
	
	public void lowerRebound(Point impact) {
		double reflectionAngle = slopeToAngle(-m);
		randomRebound(impact, LOWER_LAUNCH_BOUND, reflectionAngle);
	}
	
	public void upperRebound(Point impact) {
		double reflectionAngle = slopeToAngle(-m);
		randomRebound(impact, reflectionAngle, UPPER_LAUNCH_BOUND);
	}
	
	public static BallFunction createAtRandomAngle(Point startPos) {
		double startAngle = randomAngle(LOWER_LAUNCH_BOUND, UPPER_LAUNCH_BOUND);
		double m = angleToSlope(startAngle);
		double b = intersection(startPos, m);
		BallFunction function = new BallFunction(m, b);
		return function;
	}
}
